ZF.add('dom-attr', function(Z) {

    var D = Z.Dom,
        S = Z.String,
        ie = Z.Browser.ie,
        
        supports = {
            html : 1,
            text : 1
        },
        
        attributes = {
            'readonly' : 'readOnly',
            'for' : 'htmlFor',
            'class' : ie ? 'className' : 'class'
        },
        
        attrNormalizers = {
            tabIndex : {
                geter : function(el) {
                    return el.tabIndex;
                },
                seter : function(el, value) {
                    // http://www.w3.org/TR/html5/editing.html#sequential-focus-navigation-and-the-tabindex-attribute
                    if (isNaN(parseInt(value))) {
                        el.removeAttribute("tabindex");
                        el.removeAttribute("tabIndex");
                    } else {
                        el.tabIndex = val;
                    }
                }
            },
            // 在标准浏览器下，用 getAttribute 获取 style 值
            // IE7- 下，需要用 cssText 来获取
            // 统一使用 cssText
            style : {
                geter : function(el) {
                    return el.style.cssText;
                },
                seter : function(el, value) {
                    el.style.cssText = value;
                }
            },
            checked : {
                seter : function(el, value) {
                    el.checked = !!value;
                }
            }
        },
        
        RE_SPECIAL_ATTRS = /^(?:href|src|style)/,
        RE_NORMALIZED_ATTRS = /^(?:href|src|colspan|rowspan)/,
        RE_RETURN = /\r/g,
        RE_RADIO_CHECK = /^(?:radio|checkbox)/;

    Z.extend(D, {

        // 目前仅支持 #id 或 element
        attr : function(selector, name, value, pass) {

            // Dom.attr(el, { width : 1, height : 2 ... });
            if (Z.isPlainObject(name)) {
                pass = value;
                for (var k in name) {
                    D.attr(selector, k, name[k], pass);
                }
                return;
            }

            name = S.trim(name);
            if (!name) {
                return undefined;
            }

            // has support attr function
            if (pass && supports[name]) {
                return D[name](selector, value);
            }

            // custom 
            name = attributes[name] || name;

            var el = D.get(selector),
                anl = attrNormalizers[name];

            // set
            if (arguments.length > 2) {

                if (!D.isElement(el)) {
                    return this;
                }

                if (anl && anl.seter) {
                    anl.seter(el, value);
                } else {
                    // convert the value to a string (all browsers do this but IE)
                    el.setAttribute(name, '' + value);
                }

            } else { // get

                if (!D.isElement(el)) {
                    return;
                }

                if (anl && anl.geter) {
                    return anl.geter(el);
                }

                var ret;

                // 优先用 el[name] 获取 mapping 属性值：
                // - 可以正确获取 readonly, checked, selected 等特殊 mapping 属性值
                // - 可以获取用 getAttribute 不一定能获取到的值，比如 tabindex 默认值
                // - href, src 直接获取的是 normalized 后的值，排除掉
                // - style 需要用 getAttribute 来获取字符串值，也排除掉
                if (!RE_SPECIAL_ATTRS.test(name)) {
                    ret = el[name];
                }

                // 用 getAttribute 获取非 mapping 属性和 href/src/style 的值：
                if (ret === undefined) {
                    ret = el.getAttribute(name);
                }

                // fix ie bugs
                if (oldIE) {
                    // 不光是 href, src, 还有 rowspan 等非 mapping 属性，也需要用第 2 个参数来获取原始值
                    if (RE_NORMALIZED_ATTRS.test(name)) {
                        ret = el.getAttribute(name, 2);
                    }
                }

                // 对于不存在的属性，统一返回 undefined
                return ret === null ? undefined : ret;
            }

        }

    });

}, { requires : ['dom', 'dom-query', 'dom-style'] });
